#version 140

uniform vec3 instance_positions[512];
in vec4 vertices;
in vec4 texcoords;

uniform mat4 matrix_projection;
uniform mat4 matrix_world;
uniform mat4 matrix_view;

uniform vec4 light_ambient;
uniform vec4 light_diffuse;
uniform vec4 light_specular;
uniform vec4 light_position;
uniform float light_range;

uniform vec4 material_ambient;
uniform vec4 material_diffuse;
uniform vec4 material_specular;
uniform float material_shininess;
uniform vec4 material_emission;

out vec2 texCoord;

mat4 matrix_modelview = matrix_view * matrix_world;

void main(void)
{
  vec3 instance_position = instance_positions[gl_InstanceID];
  vec4 pos = vec4(vertices.xyz, 0.0) + matrix_modelview * vec4(instance_position, 1.0);

  texCoord = texcoords.xy;

  vec3 v_to_l   = (matrix_view * light_position).xyz - pos.xyz;
  float distance = length (v_to_l);
  v_to_l = normalize (v_to_l);
  vec3 v_to_e  = normalize (-pos.xyz);
	vec3 normal = (matrix_view * matrix_world * vec4(0, 1, 0, 0)).xyz;
	normal = normalize (normal);
  gl_FrontColor = light_ambient * material_ambient;

  // the diffuse term
  float dt = max(0.0, (dot (v_to_l, normal)));
  gl_FrontColor += dt * light_diffuse * material_diffuse;

  // the specular terim
  vec3 half = normalize (v_to_e + v_to_l);
  float st = pow(max(0.0, min(1.0, dot(normal, half))), material_shininess);
  gl_FrontColor += st * light_specular * material_specular;

  gl_FrontColor += material_emission;

  float lightIntensity = clamp(1.0 - distance / light_range, 0.0, 1.0f);
  gl_FrontColor *= lightIntensity;

  gl_FrontColor = clamp (gl_FrontColor, 0, 1);

  gl_Position = matrix_projection * pos;
}
